<?php

namespace App\Services\Stats\User\Elasticsearch;

use App\Core\Traits\Numeral;
use App\Models\Game\Platform\Org;
use App\Models\Game\User\User;
use App\Services\Service;
use App\Services\Traits\DatabaseElasticsearch;
use App\Models\Elasticsearch\Settlement\Info as SettlementInfo;
use Helper\Timed;

class PlayerBetService extends Service
{
	use DatabaseElasticsearch, Numeral;


	/**
	 * 获取数据列表【小时】
	 *
	 * @param \Illuminate\Http\Request $request
	 * @param bool $export
	 * @return \Illuminate\Database\Eloquent\Collection[]|int[]|array[]
	 */
	public function hour($request, $export = false)
	{
		return $this->getList($request, 'hour', $export);
	}

	/**
	 * 获取数据列表【天】
	 *
	 * @param \Illuminate\Http\Request $request
	 * @param bool $export
	 * @return \Illuminate\Database\Eloquent\Collection[]|int[]|array[]
	 */
	public function day($request, $export = false)
	{
		return $this->getList($request, '1d', $export);
	}

	/**
	 * 获取数据列表【月】
	 *
	 * @param \Illuminate\Http\Request $request
	 * @param bool $export
	 * @return \Illuminate\Database\Eloquent\Collection[]|int[]|array[]
	 */
	public function month($request, $export = false)
	{
		$datetime = $request->input('datetime');

		date_default_timezone_set(Timed::getJsLocalTimezoneNameByCookie());
		$end_time = strtotime(date('Y-m-01', strtotime('+1 month', $datetime[1])));
		if (!empty($datetime)) {
			$request->merge(['datetime' => [
				$datetime[0],
				$end_time - 1,
			]]);
		}

		return $this->getList($request, '1M', $export);
	}
	/**
	 * 获取游戏统计USD
	 *
	 * @param \Illuminate\Http\Request $request
	 * @param bool $export
	 * @return array[]|int[]|array[]
	 */
	public function getList($request, $groupBy, $export = false)
	{
		$params = ['body' => ['size' => 0]];

		// 筛选【状态】
		$this->makeWhere($params, 'status', SettlementInfo::STATUS_NORMAL);
		// 筛选【类型】
		$this->makeWhere($params, 'player_type', SettlementInfo::PLAYER_TYPE);
		// 筛选【平台】
		$this->makeWhereParamOrg($request, $params);
		// 筛选【平台】【排除】
		$this->makeWhereParamNot($request, 'plat_code_exclude', $params, 'plat_code');
		// 筛选【时间】
		$this->makeWhereParamDatetime($request, $params, 'end_time', 'datetime', SettlementInfo::INDEX_NAME, '', '', $groupBy);
		// 筛选【游戏】
		$this->makeWhereParam($request, 'game_id', $params);
		// 筛选【游戏】【排除】
		$this->makeWhereParamNot($request, 'game_id_exclude', $params, 'game_id');
		// 筛选【币种】
		$this->makeWhereParam($request, 'currency', $params);
		// 筛选【币种】【排除】
		$this->makeWhereParamNot($request, 'currency_exclude', $params, 'currency');
		// 筛选【搜索】
		$this->makeWhereParamSearch($request, $params);

		//统计usd
		$this->makeAggs($params, 'sum', ['usd.bet_base', 'usd.bet_num', 'usd.gain_player']);
		//按币种统计
		$this->makeGroupAggs($request, $params, 'sum', ['bet_num', 'gain_player', 'bet_base'], ['currency']);
		$currencyStats = SettlementInfo::search($params);
		// 列表数据
		$this->makeGroupDatetimeAggs($request, $params, 'sum', ['bet_num', 'gain_player', 'bet_base', 'usd.bet_base', 'usd.bet_num', 'usd.gain_player'], ['currency', 'plat_code', 'uid', 'game_id'], "group_str", $groupBy);

		//排序
		$order_column = $request->input('order_column', 'bet_base');
		switch ($order_column){
			case "doc_count":
				$order_column = '_count';
				break;
			case "timed":
				$order_column = '_key';
				break;
		}
		$this->makeAggsOrderParam($request, $params, $order_column);

		$aggAll = SettlementInfo::search($params);
		// 数据条数
		$total = isset($aggAll['aggregations']) ? count($aggAll['aggregations']['group']['buckets']) : 0;

		//分页
		$this->makeAggsPaginationParam($request, $params);

		// 查询数据
		$results = SettlementInfo::search($params);

		// 数据处理
		// 统计
		$stats = $this->getStats($currencyStats['aggregations'] ?? null, $request);
		//分页
		$result= $this->getData($results['aggregations'] ?? null, $request, $groupBy);

		return [
			$result['data'],
			$total,
			$stats['stat'],
		];
	}

	private function getStats($aggs, $request)
	{
		if (is_null($aggs)) {
			return [
				'stat' => [
					'usd' => [],
					'sts' => [],
				],
			];
		}

		// USD【合计】
		$usd = [
			'gain_player' => $aggs['usd.gain_player']['value'],
			'amount' => -$aggs['usd.gain_player']['value'],
			'bet_base' => $aggs['usd.bet_base']['value'],
			'bet_num' => $aggs['usd.bet_num']['value'],
			'doc_count' => 0,
		];

		// 分分币种【合计】
		$currency = [];

		collect($aggs['group']['buckets'])->map(function ($item)use(&$usd, &$currency, $request) {

			if(!isset($currency[$item['key']['currency']])){
				$currency[$item['key']['currency']] = [
					'bet_base' => 0,
					'bet_num' => 0,
					'currency' => $item['key']['currency'],
					'doc_count' => 0,
					'gain_player' => 0,
					'amount' => 0,
				];
			}

			$usd['doc_count'] += $item['doc_count'];

			$currency[$item['key']['currency']]['bet_base'] += $item['bet_base']['value'];
			$currency[$item['key']['currency']]['bet_num'] += $item['bet_num']['value'];
			$currency[$item['key']['currency']]['doc_count'] += $item['doc_count'];
			$currency[$item['key']['currency']]['gain_player'] += $item['gain_player']['value'];
			$currency[$item['key']['currency']]['amount'] += -$item['gain_player']['value'];
		});

		return [
			'stat' => [
				'usd' => $usd,
				'sts' => array_values($currency),
			],
		];
	}

	private function getData($aggs, $request, $group_by='1d')
	{
		if (is_null($aggs)) {
			return ['data' => []];
		}


		$data = collect($aggs['group']['buckets'])->map(function ($item)use(&$usd, &$currency, $request, $group_by) {

			$grouopArr = explode('_', rtrim($item['key']['group_str'], '_'));

			return [
				'amount' => -$item['gain_player']['value'],
				'gain_player' => $item['gain_player']['value'],
				'bet_base' => $item['bet_base']['value'],
				'bet_num' => $item['bet_num']['value'],
				'currency' => $grouopArr[0],
				'plat_code' => $grouopArr[1],
				'uid' => $grouopArr[2],
				'game_id' => $grouopArr[3],
				'doc_count' => $item['doc_count'],
				'group_by' => $group_by,
				'time_zone' => Timed::getTimezoneName(),
				'timed' => $item['key']['timed'],
				'usd'=>
					[
						'amount' => -$item['usd.gain_player']['value'],
						'bet_base' => $item['usd.bet_base']['value'],
						'bet_num' => $item['usd.bet_num']['value'],
						'gain_player' => $item['usd.gain_player']['value'],
					],
			];
		});

		//查询account_id
		$uids = array_column($data->toArray(), 'uid');
		$users = User::whereIn('id', $uids)->select(['account_id', 'id'])->get()->toArray();
		$userArr = array_column($users, 'account_id', 'id');

		//查询org
		$plat_codes = array_column($data->toArray(), 'plat_code');
		$orgs = Org::whereIn('code', $plat_codes)->select(['code', 'name'])->get()->toArray();
		$orgArr = array_column($orgs, 'name', 'code');

		$data->transform(function ($item)use($orgArr, $userArr) {
			return $item + [
					'account_id' => isset($userArr[$item['uid']]) ? $userArr[$item['uid']] : $item['uid'],
					'org' => [
						'code' => $item['plat_code'],
						'name' => isset($orgArr[$item['plat_code']]) ? $orgArr[$item['plat_code']] : $item['plat_code'],
					],];
		});

		return [
			'data' => $data,
		];
	}

}
